<?php
/**
 * Created by PhpStorm.
 * User: BlueIdeaLirui
 * Date: 2019/09/04
 * Time: 14:58
 */

namespace business\elasticsearch\services;

use business\base\models\AreaModel;
use business\base\services\DictionaryService;
use business\base\services\ScoreItemsService as ScoreItems;
use business\base\services\StopWordsService;
use business\base\services\SynonymWordsService;
use business\base\services\SystemConfigService;
use business\company\services\SelectionSupplierService;
use business\elasticsearch\models\IntegrateSupplierModel;
use business\elasticsearch\repositories\IntegrateSupplierRepository;
use common\utils\AreaAnalyzerUtils;
use common\utils\StringUtils;
use yii\elasticsearch\Command;
use business\base\services\AreaService;
use common\utils\MoneyUtil;
use common\utils\DomainUtil;

class IntegrateSupplierService
{
    /**
     * @var string 查询入口，pc端|移动端/脚本（cron）
     */
    public $portal = 'pc';

    private $matchBasicCategoryName = 'basicCategoryName';//todo 功能：只匹配前三个分类，则改为 basicCategoryNameFirst3  同时需要确保es入库脚本以及执行索引更新
    private $matchBasicCategoryCode = 'basicCategoryCode';//todo 功能：只匹配前三个分类，则改为 basicCategoryCodeFirst3  同时需要确保es入库脚本以及执行索引更新

    private $matchBasicCategoryCode2 = 'basicCategoryCode2';

//    private $matchBasicCategoryName = 'basicCategoryNameFirst3';//todo 功能：只匹配前三个分类，则改为 basicCategoryNameFirst3  同时需要确保es入库脚本以及执行索引更新
//    private $matchBasicCategoryCode = 'basicCategoryCodeFirst3';//todo 功能：只匹配前三个分类，则改为 basicCategoryCodeFirst3  同时需要确保es入库脚本以及执行索引更新

    private $tagStart = '<em class="_high">';
    private $tagEnd = '</em>';

    /**
     * 返回标签
     * @param string $companyNames
     * @return array
     */
    public function getTags($companyNames = '')
    {
        $query = $bool = [];

        if (!empty($companyNames)) {
            $companyNames = explode(',', $companyNames);
            $size = count($companyNames);
            $boolKey = 0;
            if (!empty($companyNames)) {
                foreach ($companyNames as $companyName) {
                    $bool['filter']['bool']['must'][$boolKey]['bool']['should'][] = [
                        'match_phrase' => [
                            'companyName.keyword' => $companyName
                        ]
                    ];
                }
            }
            !empty($bool) && $query['function_score']['query']['bool'] = $bool;
        }

        $include = [];
        list(, $data) = (new IntegrateSupplierRepository())->queryList($query, $include, 0, $size);
        $this->tagsFilter($data);
        $this->tagsFilterV2($data);

        $rtnData = [];
        if (!empty($data)) {
            foreach ($data as $item) {
                $source = $item['_source'];
                $rtnData[] = [
                    'companyName' => $source['companyName'],
                    'regCapital' => !empty($source['regCapital']) ? $source['regCapital'] : 0,
                    'regCapitalUnit' => $source['regCapitalUnit'],
                    'regCapitalNation' => $source['regCapitalNation'],
                    'inStorageCount' => !empty($source['inStorageCount']) ? $source['inStorageCount'] : 0,
                    'recommendCount' => !empty($source['recommendCount']) ? $source['recommendCount'] : 0,
                    'projectCount' => !empty($source['projectCount']) ? $source['projectCount'] : 0,
                    'linkNumber' => !empty($source['linkNumber']) ? $source['linkNumber'] : 0,
//                    'supplierTags' => !empty($source['supplierTags']) ? $source['supplierTags'] : [],
                    'supplierTagNames' => isset($source['supplierTagNames']) && !empty($source['supplierTagNames']) ? $source['supplierTagNames'] : [],
                    'tagList' => isset($source['tagList']) && !empty($source['tagList']) ? $source['tagList'] : []
                ];
            }
        }

        return $rtnData;
    }

    /**
     * 通过公司名称查询列表
     * @param $companyNames
     * @param $page
     * @param $pageSize
     */
    public function getListByCompanyNames
    (
        $companyNames,
        $page,
        $pageSize
    )
    {
        $page = max($page, 1);
        //查询条件结构
        $query = [
            'function_score' => [
                'query' => [
                    'bool' => [
                        'must' => [],
                        'should' => [],
                    ]
                ],
                'functions' => [],
                'score_mode' => 'sum',
                'boost_mode' => 'sum',
            ],
        ];

        $bool = [];

        if (!empty($companyNames)) {
            $companyNames = explode(',', $companyNames);
            $size = count($companyNames);
            $boolKey = 0;
            if (!empty($companyNames)) {
                foreach ($companyNames as $companyName) {
                    $bool['filter']['bool']['must'][$boolKey]['bool']['should'][] = [
                        'match_phrase' => [
                            'companyName.keyword' => $companyName
                        ]
                    ];
                }
            }
            !empty($bool) && $query['function_score']['query']['bool'] = $bool;
        }

        //如果存在must条件，则要求should条件必须满足一条
        if (!empty($query['function_score']['query']['bool']['should'])) {
            $query['function_score']['query']['bool']['minimum_should_match'] = 1;
        }

        $from = ($page - 1) * $pageSize;

        $include = $highlight = $orderBy = [];

        $this->setMemberScore($query, []);

        list(, $data) = (new IntegrateSupplierRepository())->queryList($query, $include, $from, $size, [], []);

        $this->tagsFilter($data);

        $rtnData = [];
        if (!empty($data)) {
            foreach ($data as $item) {
                $source = $item['_source'];
                $rtnData[] = [
                    'companyName' => $source['companyName'],
                    'isDiamondSupplier' => $source['isDiamondSupplier'],
                    'isRegionalDiamond' => $source['isRegionalDiamond']??0,
                    'regCapital' => !empty($source['regCapital']) ? $source['regCapital'] : 0,
                    'regCapitalUnit' => $source['regCapitalUnit'],
                    'regCapitalNation' => $source['regCapitalNation'],
                    'inStorageCount' => !empty($source['inStorageCount']) ? $source['inStorageCount'] : 0,
                    'recommendCount' => !empty($source['recommendCount']) ? $source['recommendCount'] : 0,
                    'projectCount' => !empty($source['projectCount']) ? $source['projectCount'] : 0,
                    'linkNumber' => !empty($source['linkNumber']) ? $source['linkNumber'] : 0,
                    'tagList' => isset($source['tagList']) && !empty($source['tagList']) ? $source['tagList'] : [],

                    // 2021-05-11 新增字段 author:陈伟锐
                    'supplierId' => $source['supplierId'],
                    // 服务区域
                    'serviceLocationName' => $source['serviceLocationName'] ? $source['serviceLocationName'] : "",
                    // 成立年份
                    'establishYear' => $source['establishYear'] ? $source['establishYear'] : "",
                ];
            }
        }

        return $rtnData;
    }

    /**
     * @uses 根据供应商公司id获取列表
     */
    public function getListBySupplierIds($supplierIds)
    {
        //查询条件结构
        $query = [
            'terms' => [
                'supplierId.keyword' => $supplierIds
            ],
        ];
        $include = ["supplierId", "shortName","recommendCount", "regCapital","regCapitalUnit", "serviceLocationName", "basicCategoryName", "companyName", "establishYear", "projectCount", "linkNumber", "companyLogo", "isDiamondSupplier", "isRegionalDiamond", "regLocationCode", "regLocationCity", "brand"];
        list($total, $data) = (new IntegrateSupplierRepository())->queryList($query, $include, 0, count($supplierIds));
        if($total == 0){
            return [];
        }

        $wapUrl = DomainUtil::getDomainLink('WapNet', '');
        $temp = [];

        foreach($data as $v){
            $item = $v["_source"];
            $temp[]=[
                "supplier_id"=>$item["supplierId"],
                "registered_Fund"=>MoneyUtil::showFormat($item["regCapital"], $item["regCapitalUnit"]),
                "service_area"=>$item["serviceLocationName"]??"",
                "categories"=>!empty($item["basicCategoryName"]) ? implode("，",$item["basicCategoryName"]) : "",
                "supplier_name"=>$item["companyName"],
                "short_name" => $item["shortName"],
                "establish_year"=>$item["establishYear"],
                "case_num"=>$item["projectCount"],
                "contacts_count" => $item["linkNumber"],
                "company_logo" => $item["companyLogo"],
                "is_diamond_supplier" => $item["isDiamondSupplier"],
                "is_regional_diamond" => $item["isRegionalDiamond"],
                "reg_location_code" => $item["regLocationCode"],
                "reg_location_city" => $item["regLocationCity"],
                "brand" => $item["brand"]??"",
                "supplier_url" => $wapUrl . '/g/' . strtolower($item["supplierId"]),
                "recommend_count" => $item['recommendCount'],
            ];
        }
        return $temp;
    }

    /**
     * 获取查询列表
     *
     * @param $keyword
     * @param $area
     * @param $registerCapital
     * @param $registerCapitalEnd
     * @param $suppliserTags
     * @param $page
     * @param $pageSize
     * @param $orderBy
     * @param $options
     * @param $customScore
     * @return array
     * @throws \yii\db\Exception
     */
    public function getList
    (
        $keyword,
        $area,
        $registerCapital,
        $registerCapitalEnd,
        $suppliserTags,
        $page,
        $pageSize,
        $orderBy = '',
        $options = [], //其它查询参数 serviceLocationCode basicCategoryCode 等
        $customScore = true
    )
    {
        $query = [];
        $page = max($page, 1);

        $keywordList = trim($keyword) ? explode("@@##", $keyword) : [];
        $area = trim($area) ? explode(",", $area) : [];
        $options['basicCategoryCode'] = trim($options['basicCategoryCode']) ? explode(",", $options['basicCategoryCode']) : [];

        // 分析检索词
        $deriveList = $this->analyseKeyword($keywordList, $options['searchScope']);
        // 构建查询条件
        $this->builderQueryConds($query, $keywordList, $area, $registerCapital, $registerCapitalEnd, $suppliserTags, $options, $deriveList);

        $from = ($page - 1) * $pageSize;

        $include = [];

        //高亮处理
        $tagStart = $this->tagStart;
        $tagEnd = $this->tagEnd;
        $highlight = [
            'pre_tags' => [$tagStart],
            'post_tags' => [$tagEnd],
            "fields" => [
                "companyName" => new \stdClass(),
                'basicCategoryName' => new \stdClass(),
                'companyIntro' => new \stdClass(),
                'productName' => new \stdClass(),
                'projectLocationName' => new \stdClass(),
                'projectDeveloperName' => new \stdClass(),
                'projectName' => new \stdClass()
            ]
        ];
        if (!empty($orderBy)) {
            if ($orderBy == 'regSort') {//注册资金排序
                $orderBy = ['regCapital' => SORT_DESC];
            } elseif ($orderBy == 'caseSort') {//案例排序
                $orderBy = ['projectCount' => SORT_DESC];
            } elseif ($orderBy == 'inStorageSort') { //入库次数排序
                $orderBy = ['inStorageCount' => SORT_DESC];
            } elseif ($orderBy == 'recommendSort') {    //被推荐次数排序
                $orderBy = ['recommendCount' => SORT_DESC];
            } elseif ($orderBy == 'regRecruitCount') {  //报名招募次数
                $orderBy = ['regRecruitCount' => SORT_DESC];
            }
        }
        $orderBy = empty($orderBy) ? [] : $orderBy;

        list($total, $data) = (new IntegrateSupplierRepository())->queryList($query, $include, $from, $pageSize, $highlight, $orderBy);

        $this->tagsFilter($data);

        $result = ['resultNum' => $total, 'resultSet' => []];

        if (!empty($data)) {
            foreach ($data as $dv) {
                $tmp = $dv['_source'];
                $tmp['score'] = $dv['_score'];//综合评分
                // 兼容老接口
                $tmp['companySupplierId'] = $tmp['supplierId'];
                if (!empty($dv['highlight'])) {
                    foreach ($dv['highlight'] as $key => $value) {
                        if ($key == 'supplierBusinessName') {
                            $tmp['supplierBusinessNameHL'] = StringUtils::highlightString(!empty($tmp['supplierBusinessName']) ? $tmp['supplierBusinessName'] : [], $keyword);
                        } else {
                            $tmp[$key . 'HL'] = isset($value[0]) ? $value[0] : '';

                            //array 完整的高亮信息， 目前用于分类的多个高亮， 公司名称高亮可以继续使用HL
                            $tmp[$key . 'HLS'] = $value;
                        }
                    }
                }
                $catWords = $options['catWord'] ?? '';
                $keyword = $keyword ?: '';
                if (empty($catWords)) {
                    $catWords = $keyword;
                } else {
                    if ($keyword) {
                        $catWords = $catWords . '@@##' . $keyword;
                    }
                }
                //分类词高亮特殊处理
                $tmp = $this->handleCatHeightLine($tmp, $catWords);

                // 项目所在地 转成二维数组
                $tmp['projectLocationName'] = $this->projectLocationNameToTwoDim($tmp['projectLocationName']);
                if (isset($tmp['projectLocationNameHLS'])) {
                    $tmp['projectLocationNameHLS'] = $this->projectLocationNameToTwoDim($tmp['projectLocationNameHLS']);
                }
                //当 搜索范围为0（不限）、1（公司名称）时，且高亮的公司名称和搜索词完全匹配时，对高亮词做特殊处理
                if (in_array($options['searchScope'], [0, 1]) && isset($tmp['companyNameHL']) && strip_tags($tmp['companyNameHL']) == $keyword) {
                    $tmp['companyNameHL'] = $this->tagStart . $keyword . $this->tagEnd;
                }

                $now = time();
                if ($options['searchScope'] == 0 && (isset($tmp['brandStartTime']) && isset($tmp['brandEndTime']) && $tmp['brandStartTime'] <= $now && $tmp['brandEndTime'] >= $now)) {
                    // 品牌词高亮处理
                    $tmp['brand'] = isset($tmp['brand']) && $tmp['brand'] == $keyword ? ($tagStart . $tmp['brand'] . $tagEnd) : $tmp['brand'];
                }

                $result['resultSet'][] = $tmp;
            }
        }

        //添加搜索记录
        if ((int)$page === 1) {
            (new SearchLogsService())->addSearchRecord($keyword, $keyword, $total, 'supplier', $this->portal);
        }

        return $result;
    }

    public function list()
    {
        $query = [];
        $categoryCode = \Yii::$app->request->post('category_code', []); // 服务分类
        $projectNum = \Yii::$app->request->post('project_num', 0); // 项目案例数
        $registerFund = \Yii::$app->request->post('register_fund', 0); // 注册资金
        $serviceLocationCode = \Yii::$app->request->post('service_location_code', []); // 服务区域
        $qualificationName = \Yii::$app->request->post('qualification_name', []); // 服务资质
        $projectLocationCode = \Yii::$app->request->post('project_location_code', []); // 项目所在地的code
        $page = \Yii::$app->request->post('page', 1);
        $pageSize = \Yii::$app->request->post('page_size', 10);

        $options = [
            'basicCategoryCode' => $categoryCode,
            'projectCount' => $projectNum,
            'projectLocationCode' => $projectLocationCode,
            'serviceLocationCode' => $serviceLocationCode,
            'qualificationName' => $qualificationName,
        ];

        // 构建查询条件
        $this->builderQueryConds($query, [], [], $registerFund, 9999999, '', $options, []);

        if (is_array($qualificationName) && $qualificationName) {
            $query['function_score']['query']['bool']['must'][] = [
                'terms' => [
                    'qualificationName.keyword' => $qualificationName,
                ]
            ];
        }

        $from = ($page - 1) * $pageSize;
        list(, $data) = (new IntegrateSupplierRepository())->queryList($query, [], $from, $pageSize, [], []);
        $list = [];
        if ($data) {
            foreach($data as $item) {
                array_push($list, $item["_source"]);
            }
        }
        return $list;
    }

    // 分析检索词
    private function analyseKeyword(array $keyword, $searchScope = 0)
    {
        /*
         * 1.(如果可以)拆解出area和basicCategoryCode
         * 2.匹配同义词
         * */

        $synonymWordList = $deriveLocationCodeList = $deriveBasicCategoryCodeList = $deriveLocationKeyword = $deriveOtherKeyword = [];

        // 只有当【搜索范围】为【不限】时，才对检索词进行词义分析
        if ($searchScope == 0) {
            $result = $this->handleKeywordToAreaCat($keyword);
            $deriveLocationCodeList = $result['locationCode'];
            $deriveBasicCategoryCodeList = $result['categoryCode'];
            $deriveLocationKeyword = $result['locationKeyword'];
            $deriveOtherKeyword = $result['otherKeyword'];
        }

        foreach ($keyword as $item) {
//            $filterWord = StopWordsService::filter($item); //停用词过滤
            $synonmyWord = SynonymWordsService::find($item); //转同义词
            if ($synonmyWord != $item && !in_array($synonmyWord, $synonymWordList)) {
                array_push($synonymWordList, $synonmyWord);
            }
        }

        return [
            'synonymWordList' => $synonymWordList, // 同义词
            'deriveLocationCodeList' => $deriveLocationCodeList, // 派生区域code
            'deriveBasicCategoryCodeList' => $deriveBasicCategoryCodeList, // 派生服务分类code
            'deriveLocationKeyword' => $deriveLocationKeyword, // 派生地区词
            'deriveOtherKeyword' => $deriveOtherKeyword, // 派生其它词
        ];
    }

    /**
     * @uses 关键字中存在 区域 行业分类则则过滤关键字 反之则按关键字逻辑
     */
    private function handleKeywordToAreaCat(array $keyword)
    {
        $locationCode = $categoryCode = $locationKeyword = $otherKeyword = [];
        foreach ($keyword as $word) {
            $newWord = "";
            $areaArr = [];
            $word = str_replace(" ", "", $word);
            // 把检索词拆分成【地区词】和【其它词】
            $resWord = AreaAnalyzerUtils::tokenizer($word);

            foreach ($resWord as $item) {
                if (isset($item['type']) && $item['type'] == 'words') {
                    $newWord = $item['token'];
                } else if (isset($item["type"]) && $item["type"] == "area" && !in_array($item["token"], $areaArr)) {
                    $areaArr[] = $item["token"];
                }
            }
            // 只有当检索词为【地区词】/【分类词】/【地区词+分类词】这三种情况，才会产生派生locationCode或派生categoryCode
            // 只有当$newWord大于一个字符，才尝试进行模糊匹配—服务分类（分析：从正常的用户搜索场景来看，几乎不可能使用一个字去定位服务分类）
            if ($newWord && mb_strlen($newWord) > 1) {
                $categoryCode = $this->hasCategoryWords($newWord, 2);
            }
            if (($categoryCode && $areaArr) || (!$newWord && $areaArr)) {
                $codeRes = (new AreaService())->getAreaCodesByCond(["item_name" => $areaArr], ["norm_name" => $areaArr], "item_code");
                if ($codeRes) {
                    $areaCodes = array_column($codeRes, "item_code");
                    $locationCode = array_merge($locationCode, $areaCodes);
                }
            }

            // 只有当检索词为【地区词+品牌词】，才会产生locationKeyword和otherKeyword
            foreach ($resWord as $item) {
                if ($item['type'] == 'area') {
                    array_push($locationKeyword, $item['token']);
                } else if ($item['type'] == 'words') {
                    array_push($otherKeyword, $item['token']);
                }
            }
            if (($locationCode || $categoryCode) || (!$locationKeyword || !$otherKeyword)) {
                $locationKeyword = $otherKeyword = [];
            }
        }


        return [
            'locationCode' => $locationCode,
            'categoryCode' => $categoryCode,
            'locationKeyword' => $locationKeyword,
            'otherKeyword' => $otherKeyword,
        ];

    }

    // 项目所在地 转成二维数组
    private function projectLocationNameToTwoDim(array $projectLocationName)
    {
        $twoDim = [];
        $uniqueArr = [];
        if (isset($projectLocationName) && $projectLocationName) {
            $i = 0;
            foreach ($projectLocationName as $key => $item) {
                if ($key % 2 == 0) {
                    $uniqueArr[$i] = $item;
                } else {
                    if (!in_array($uniqueArr[$i] . $item, $uniqueArr)) {
                        $twoDim[$i] = [
                            'province_name' => $uniqueArr[$i],
                            'city_name' => $item
                        ];
                        $uniqueArr[$i] .= $item;
                    }
                    $i++;
                }
            }
            $twoDim = array_values($twoDim);
        }
        return $twoDim;
    }

    public function scoreExplain($keyword, $page, $pageSize, $options = [], $explain = 0)
    {
        //查询条件结构
        $query = [
            'function_score' => [
                'query' => [
                    'bool' => [
                        'must' => [],
                        'should' => [],
                        //'minimum_should_match' => 1,
                    ]
                ],
                'functions' => [],
                'score_mode' => 'sum',
                //'boost_mode' => 'sum',
            ],
        ];
        if (!empty($options['scoreMode'])) {
            $query['function_score']['score_mode'] = 'multiply';
        }
        if (!empty($options['boostMode'])) {
            $query['function_score']['boost_mode'] = 'sum';
        }
        // 构建查询条件
        $this->builderQueryConds($query, $keyword, null, null, null, null, $options);
        //如果存在must条件，则要求should条件必须满足一条
        if (!empty($query['function_score']['query']['bool']['should'])) {
            $query['function_score']['query']['bool']['minimum_should_match'] = 1;
        }
        $from = ($page - 1) * $pageSize;
        $orderBy = [];
        $esCommand = new Command();
        $esCommand->db = \Yii::$app->get('elasticsearch');
        $esCommand->queryParts = [
            '_source' => [
                'supplierId',
                'companyName',
                'basicCategoryName',
                'categoryCodeRanks',
                'mainBusiness',
                'supplierLevel'
            ],
            'explain' => $explain ? true : false,
            'size' => $pageSize,
            'from' => $from,
            'query' => $query
        ];
        
        $esCommand->index = IntegrateSupplierModel::index();
        $esCommand->type = IntegrateSupplierModel::type();
        $preferenceStr = md5(json_encode($query) . $from . $pageSize . json_encode($orderBy));
        $data = $esCommand->search(['preference' => $preferenceStr]);

        return empty($data['hits']['hits']) ? [] : $data['hits']['hits'];
    }

    protected function handleCatHeightLine($tmp, $catWord)
    {
        try {
            if (empty($tmp[$this->matchBasicCategoryName]) || empty($catWord)) {
                return $tmp;
            }
            $catHLS = $tmp[$this->matchBasicCategoryName . 'HLS'] ?? [];
            if (!empty($catHLS)) {
                foreach ($catHLS as $val) {
                    if (strpos($val, $this->tagStart) !== false) {
                        return $tmp;
                    }
                }
            }
            $catWord = array_filter(explode('@@##', $catWord));
            $catWord = array_map(function ($v) {
                return SynonymWordsService::find(
                    StopWordsService::filter($v)
                );
            }, $catWord);
            $catList = $tmp[$this->matchBasicCategoryName];
            $matched = false;
            foreach ($catList as $key => $val) {
                foreach ($catWord as $cat) {
                    if (strpos($val, $cat) !== false) {
                        $catList[$key] = str_replace($cat, $this->tagStart . $cat . $this->tagEnd, $val);
                        $matched = true;
                    }
                }
            }

            if ($matched) {
                $tmp[$this->matchBasicCategoryName . 'HLS'] = $catList;
                $tmp[$this->matchBasicCategoryName . 'HL'] = !empty($tmp[$this->matchBasicCategoryName . 'HL']) ? $tmp[$this->matchBasicCategoryName . 'HL'] : ($catList[0] ?? '');
            }
            return $tmp;
        } catch (\Throwable $e) {
            return $tmp;
        }
    }

    protected function tagsFilterV2(&$data)
    {
        $tagsMap = ["12" => "行业十强", "13" => "高品质", "3" => "百强战略"];
        $tagsOrder = ["12" => "1", "13" => "2", "3" => "3"];
        if (!empty($data)) {
            foreach ($data as $key => $indexs) {
                $tags = $data[$key]['_source']['supplierTags'];
                if (!empty($tags)) {
                    $nameOrders = [];
                    foreach ($tags as $t) {
                        if (isset($tagsMap[$t])) {
                            $nameOrders[$tagsOrder[$t]] = $tagsMap[$t];
                        }
                    }
                    if (!empty($nameOrders)) {
                        ksort($nameOrders);
                        $data[$key]['_source']['supplierTagNames'] = array_values($nameOrders);
                    }
                }
            }
        }
    }

    /**
     * 标签数据过滤
     * @param $data
     */
    protected function tagsFilter(&$data)
    {
        if (!empty($data)) {
            foreach ($data as $key => $indexs) {
                $indexs['_source']['isTop100StrategicCooperation'] == true
                    ? $data[$key]['_source']['tagList'][] = '百强战略' : '';
                //去掉绑上有名
//                $indexs['_source']['isTop10Competitiveness'] == true
//                    ? $data[$key]['_source']['tagList'][] = '榜上有名' : '';
                $indexs['_source']['isIndustryTop'] == true
                    ? $data[$key]['_source']['tagList'][] = '行业top级' : '';
            }
        }
    }

    /**
     * 构建查询条件
     * @param array $query
     * @param $keyword
     * @param $area
     * @param $registerCapital
     * @param $registerCapitalEnd
     * @param $suppliserTags
     * @param array $options 其它搜索选项
     * @param array $deriveList 派生列表
     * @throws \yii\db\Exception
     */
    protected function builderQueryConds
    (
        &$query = [],
        array $keyword,
        array $area,
        $registerCapital,
        $registerCapitalEnd,
        $suppliserTags,
        $options = [],
        $deriveList = []
    )
    {
        $raisePhraseBoost = false;
        $deriveKeyword = $deriveList['synonymWordList'] ?? [];
        $deriveLocationCodeList = $deriveList['deriveLocationCodeList'] ?? [];
        $deriveBasicCategoryCodeList = $deriveList['deriveBasicCategoryCodeList'] ?? [];
        // 把派生地区code和area合并
        $area = array_values(array_unique(array_merge($area, $deriveLocationCodeList)));

        /*
         * 注释原因
         * 需求—例如 平台供应商名称叫 某某防水有限公司，但分类不含【防水】，用户可以使用 防水 作为搜索词，检索到这一类记录）
         * 根据需求，调整了当搜索词是【分类词】或【地区词+分词】时，不使用分类code作为过滤条件
         *
         * 备注跟进： 测试反馈效果不是很好，暂时还原
         * */
        // 把派生服务分类code和basicCategoryCode合并
        $options['basicCategoryCode'] = array_values(array_unique(array_merge($options['basicCategoryCode'], $deriveBasicCategoryCodeList)));
        // 如果没有 派生地区code 和 派生服务分类code，则假定用户要搜索公司名称，所以提高【companyName】字段的短语匹配权重
        if (!$deriveLocationCodeList && !$deriveBasicCategoryCodeList) {
            $raisePhraseBoost = true;
        }

        //查询条件结构
        $query = [
            'function_score' => [
                'query' => [
                    'bool' => [
                        'must' => [],
                        'should' => [],
                    ]
                ],
                'functions' => [],
                'score_mode' => 'sum',
                'boost_mode' => 'sum',
            ],
        ];

        // 平台寻源过滤企业状态为注销吊销的企业（公司工商状态，1-正常，2-注销，3-吊销，部分采招门户的为0）
        if ($options['channel'] == 'search'){
            $query['function_score']['query']['bool']['must'][] = [
                'range' => [
                    'companyStatus' => [
                        'lt' => 2
                    ]
                ]
            ];
        }

        //遍历评分方法
        $scoreMethod = [
//            'setRechargeScore', //根据充值金额对应分值
            //'setMemberScore', //会员等级对应分值
//            'setBasicDataScore', //基础资料对应分值
//            'setDeveloperRecommendScore', //开发商收藏推荐对应分值
            'setTagsScore', //会员标签增加对应分值
            'setAttachedScore',//设置附加加分项
            'setHitScore' // 设置命中加分项
        ];

        //根据关键字类型， 设置相关关键字类型
        $this->setKeyWordQueryByKeyType($query, $options);

        $this->setKeyWordQueryByKeyType($query, $options);

        // 筛选字段逻辑
        // 构建项目地区查询
        $this->builerAreaQuery($query, $area, $options['locationType']);

        // 构建注册资金范围查询
        $this->builderRegCapital($query, $registerCapital, $registerCapitalEnd);

        // 构建入库次数量范围查询
        $this->builderInStorageCount($query, $options['inStorageCount']);

        // 构建项目案例数量范围查询
        $this->builderProjectCount($query, $options['projectCount']);

        // 构建联系人数量范围查询（平台寻源不展示联系人为0的数据）
        $this->builderLinkNumber($query, $options['linkNumber'], $options['channel']);

        // 构建标签项查询
        $this->builderSupplierTags($query, $suppliserTags);

        //构建行业分类查询
        $this->builderBasicCategoryCodes($query, $options['basicCategoryCode'] ?? []);

        // 构建精选供应商查询
        $this->builderSupplierBoutique($query, $options['isBoutique'] ?? '');

        // 构建是否为砖石供应商
        $this->builderSupplierDiamond($query, $options['isDiamond'] ?? false);

        // 构建行业二级分类查询
        $this->builderBasicCategoryCodes2($query, $options['basicCategoryCode2'] ?? []);

        //构建服务区域查询
        $this->builderServiceLocationCodes($query, $options['serviceLocationCode'] ?? []);

        //构建项目所在地查询
        $this->builderProjectLocationCodes($query, $options['projectLocationCode'] ?? []);

        // 构建不包含查询
        if (isset($options['notContain']) && $options['notContain']) {
            $this->builderNotContainQuery($query, $options['notContain']);
        }

        //构建战采数量查询
        if ($options['strategicCaseNum']){
            $this->builderStrategicCaseNum($query,  $options['strategicCaseNum']);
        }
        //构建战采数量查询
        if ($options['turnoverNum']){
            $this->builderTurnoverNum($query,  $options['turnoverNum']);
        }
        //构建战采数量查询
        if ($options['listedType']){
            $this->builderListedType($query,  $options['listedType']);
        }

        // 把派生服务分类code和basicCategoryCode合并
        $basicCategoryCode = array_values(array_unique(array_merge($options['basicCategoryCode'], $deriveBasicCategoryCodeList)));

        $this->setMemberScore($query, $basicCategoryCode, $keyword);
        if (!empty(SystemConfigService::get('catcode_rank'))) {
            $this->setBasicCategoryCodeWeight($query, $basicCategoryCode);
        }
        if (!empty($scoreMethod)) {
            foreach ($scoreMethod as $method) {
                call_user_func_array(array($this, $method), array(&$query, $keyword, $deriveList, $raisePhraseBoost, $options['searchScope']));
            }
        }

        if (!empty($query['function_score']['query']['bool']['should'])) {
            $query['function_score']['query']['bool']['minimum_should_match'] = 1;
        }
    }

    private function builderNotContainQuery(&$query, string $keyword)
    {
        if ($keyword) {
            $query['function_score']['query']['bool']['must_not'] = [
                [
                    'match' => [
                        'companyName.keyword' => $keyword
                    ]
                ]
            ];
        }
    }

    protected function setHitScore(&$query = [], array $keyword, array $deriveList, bool $raisePhraseBoost, $searchScope)
    {
        if (!$keyword) {
            return;
        }

        $hitScoreQuery = &$query['function_score']['query']['bool'];
        $searchScope = is_numeric($searchScope) ? (int)$searchScope : 0;
        switch ($searchScope) {
            case 1:
                $fieldList = [
                    'companyName' => [
                        'match' => true,
                        'match_phrase' => true
                    ]
                ];
                break;
            case 2:
                $fieldList = [
                    'productName' => [
                        'match' => true,
                        'match_phrase' => true,
                    ]
                ];
                break;
            case 3:
                $fieldList = [
                    'projectDeveloperName' => [
                        'match' => true,
                        'match_phrase' => true,
                    ]
                ];
                break;
            case 4:
                $fieldList = [
                    'projectName' => [
                        'match' => true,
                        'match_phrase' => true,
                    ]
                ];
                break;
            default:
                $fieldList = [
                    'companyName' => [
                        'match' => true,
                        'match_phrase' => true
                    ], // 公司名称
                    'brand' => [
                        'match' => false,
                        'match_phrase' => true
                    ], // 品牌词
                    'basicCategoryName' => [
                        'match' => true,
                        'match_phrase' => true,
                    ], // 行业分类
                    'productName' => [
                        'match' => true,
                        'match_phrase' => false,
                    ], // 经营产品
                    'projectDeveloperName' => [
                        'match' => true,
                        'match_phrase' => false,
                    ], // 合作开发商
                    'projectName' => [
                        'match' => true,
                        'match_phrase' => false,
                    ] // 项目案例
                ];
        }
        foreach ($fieldList as $field => $value) {
            $boost = (int)ScoreItems::get($field);
            $matchBoost['boost'] = $boost;
            $matchPhraseKeywordBoost['boost'] = $boost * 2;
            // 如果搜索范围不为【不限】，则提高【公司名称/经营产品/合作开发商/项目案例】的权重
            // 目的是降低付费供应商对检索词相关度的影响
            if (in_array($searchScope, [1, 2, 3, 4])) {
                $matchBoost['boost'] = $boost * 10;
                $matchPhraseKeywordBoost['boost'] = $boost * 20;
            }
            if ($searchScope == 0 && ($field == 'brand' || ($raisePhraseBoost && $field == 'companyName'))) {
                $matchBoost['boost'] = $boost * 20;
                $matchPhraseKeywordBoost['boost'] = 10000;
            }

            $this->setHitKeywordScore($hitScoreQuery, $keyword, $field, $value, $matchBoost, $matchPhraseKeywordBoost, $deriveList['deriveLocationKeyword'], $deriveList['deriveOtherKeyword']);
            if ($deriveList['synonymWordList']) {
                $this->setHitKeywordScore($hitScoreQuery, $deriveList['synonymWordList'], $field, $value, $matchBoost, $matchPhraseKeywordBoost);
            }
        }
    }

    private function setHitKeywordScore(
        &$hitScoreQuery,
        $keyword,
        $field,
        $value,
        $matchBoost,
        $matchPhraseKeywordBoost,
        $deriveLocationKeyword = [],
        $deriveOtherKeyword = []
    )
    {
        foreach ($keyword as $word) {
            if ($value['match']) {
                // 分词检索
                if ($deriveLocationKeyword && $deriveOtherKeyword) {
                    $hitScoreQuery['should'][] = [
                        'match' => [
                            $field => array_merge([
                                'query' => implode(" ", $deriveLocationKeyword),
                                'analyzer' => 'ik_smart'
                            ], ['boost' => ceil($matchBoost['boost'] / 10)]),
                        ]
                    ];
                    $hitScoreQuery['should'][] = [
                        'match' => [
                            $field => array_merge([
                                'query' => implode(" ", $deriveOtherKeyword),
                                'analyzer' => 'ik_smart'
                            ], $matchBoost),
                        ]
                    ];
                } else {
                    $hitScoreQuery['should'][] = [
                        'match' => [
                            $field => array_merge([
                                'query' => $word,
                                'analyzer' => 'ik_smart'
                            ], $matchBoost),
                        ]
                    ];
                }
            }
            if ($value['match_phrase']) {
                // 全词检索
                if ($field == 'brand') { // 品牌词的全词匹配，还需要结合品牌词有效期作为筛选条件
                    $now = time();
                    $hitScoreQuery['should'][] = [
                        'bool' => [
                            'must' => [
                                [
                                    'match_phrase' => [
                                        "{$field}.keyword" => array_merge(['query' => $word], $matchPhraseKeywordBoost)
                                    ]
                                ],
                                [
                                    'range' => [
                                        'brandStartTime' => [
                                            'lte' => $now
                                        ]
                                    ]
                                ],
                                [
                                    'range' => [
                                        'brandEndTime' => [
                                            'gte' => $now
                                        ]
                                    ]
                                ],
                            ]
                        ]
                    ];
                } else {
                    $hitScoreQuery['should'][] = [
                        'match_phrase' => [
                            "{$field}.keyword" => array_merge(['query' => $word], $matchPhraseKeywordBoost)
                        ]
                    ];
                }

                if ($field == "companyName") {
                    $hitScoreQuery['should'][] = [
                        'match_phrase' => [
                            'companyName' => array_merge(
                                [
                                    'query' => $word,
                                    'analyzer' => 'ik_smart',
                                    'slop' => 50
                                ], $matchBoost)
                        ]
                    ];
                }
            }
        }
    }

    /**
     * 设置命中加分项
     * @param array $query
     * @param $customScore
     * @param $keyword
     */
    protected function setHitScore2(&$query = [], $keyword, $customScore = true, $searchScope)
    {
        $searchScope = is_numeric($searchScope) ? (int)$searchScope : 0;
        if (!empty($keyword)) {
            $hitScoreQuery = &$query['function_score']['query']['bool'];

            switch ($searchScope) {
                case 1:
                    $fields = ['companyName'];
                    break;
                case 2:
                    $fields = ['productName'];
                    break;
                case 3:
                    $fields = ['projectDeveloperName'];
                    break;
                case 4:
                    $fields = ['projectName'];
                    break;
                default:
                    $fields = [
                        'companyName', // 公司名称
                        'basicCategoryName', // 行业分类
                        'productName', // 经营产品
                        'projectDeveloperName', // 合作开发商
                        'projectName' // 项目案例
                    ];
            }
            if (!empty($fields)) {
                $matchPhraseBoost = $customScore ? ['boost' => 1000] : [];
                $keywordMatchBoost = $customScore ? ['boost' => 100000] : [];
                $basicCategoryNameKeywordMatchBoost = $customScore ? ['boost' => 10000] : [];
                foreach ($fields as $field) {
                    $boost = $customScore ? ['boost' => (int)ScoreItems::get($field)] : [];
                    $kb = ($field == 'basicCategoryName') ? $basicCategoryNameKeywordMatchBoost : $keywordMatchBoost;
                    foreach ($keyword as $word) {
                        $hitScoreQuery['should'][] = [
                            'match' => [
                                $field => array_merge([
                                    'query' => $this->effectWords($word, $field),
                                    'analyzer' => 'ik_smart'
                                ], $boost),
                            ]
                        ];
                        $hitScoreQuery['should'][] = [
                            'match_phrase' => [
                                "{$field}.keyword" => array_merge(['query' => $word], $kb)
                            ]
                        ];
                        if ($field == "companyName") {
                            $hitScoreQuery['should'][] = [
                                'match_phrase' => ['companyName' => array_merge(['query' => $word, 'slop' => 2], $matchPhraseBoost)]
                            ];
                        }
                    }
                }
            }
        }

        $hitScoreQuery['minimum_should_match'] = 1;
    }

    /**
     * 按地区用空格分割词
     * @param $keyword
     * @return string
     */
    protected function splitWords($keyword)
    {
        $keywords = AreaAnalyzerUtils::tokenizer($keyword);
        return implode(' ', array_values(array_column($keywords, 'token')));
    }

    protected function effectWords($keyword, $field = '')
    {
//        $keywordsInfo = AreaAnalyzerUtils::tokenizerInfo($keyword);
//        if (in_array($field,['shortName','basicCategoryName'])) {
//            //如果拆出来的词全是地名，用地名去查
//            if ($keywordsInfo['numTotal'] == $keywordsInfo['areasNum']) {
//                return implode(' ',$keywordsInfo['areas']);
//            }
//            //如果不是，地名不参与查询
//            return implode(' ',$keywordsInfo['words']);
//        }
        return $this->splitWords($keyword);
    }

    /**
     * 判断搜索关键词是否是分类词
     * @throws \yii\db\Exception
     */
    protected function hasCategoryWords($keyword, $type = 1)
    {
        if ($type == 1) {
            $sql = "select * from `b2b_parameter`.`bsp_basic_forest` where category_status=1 and is_leaf=1 and category_name = '" . $keyword . "'";
        } else {
            $sql = "select * from `b2b_parameter`.`bsp_basic_forest` where category_status=1 and is_leaf=1 and category_name like '%" . $keyword . "%'";
        }
        $data = \Yii::$app->db->createCommand($sql)->queryAll();
        $data = !empty($data) ? array_column($data, 'category_code') : [];
        return $data;
//        return empty($data) ? false : true;
    }

    //针对分类词模糊搜索
    protected function setCatWordQuery(& $query, $catWord = '')
    {
        //同义词查询，以及停用词过滤
        $catWord = SynonymWordsService::find(
            StopWordsService::filter($catWord)
        );

        $catWord = explode('@@##', $catWord);
        foreach ($catWord as $word) {

            //只有一个字分类搜索，先进行模糊匹配所有分类code
            if (mb_strlen($word) == 1) {
                $catCodes = $this->hasCategoryWords($word, 2);
                if (!empty($catCodes)) {
                    $query['function_score']['query']['bool']['should'][] = [
                        'terms' => [
                            $this->matchBasicCategoryCode => $catCodes,
                        ]
                    ];
                }
            }


            //使用ik_smart 使用高分值，为了最佳匹配
            $query['function_score']['query']['bool']['should'][] = [
                'match' => [
                    $this->matchBasicCategoryName => [
                        'query' => $word,
                        'boost' => (int)ScoreItems::get('basicCategoryName'),
                        "analyzer" => 'ik_smart',
                    ]
                ]
            ];
            //正常分词匹配，取正常的一般分支，为了兼容原来的结果，避免没有结果的情况
            $query['function_score']['query']['bool']['should'][] = [
                'match' => [
                    $this->matchBasicCategoryName => [
                        'query' => $word,
                        'boost' => (int)(ScoreItems::get('basicCategoryName') / 5),
                    ]
                ]
            ];
        }
    }

    //针对公司名称模糊搜索
    protected function setCompanyWordQuery(& $query, $companyWord = '')
    {
        //同义词查询，以及停用词过滤
        $companyWord = SynonymWordsService::find(
            StopWordsService::filter($companyWord)
        );

        $companyWord = explode('@@##', $companyWord);
        foreach ($companyWord as $word) {
            //使用ik_smart 使用高分值，为了最佳匹配
            $query['function_score']['query']['bool']['should'][] = [
                'match' => [
                    'companyName' => [
                        'query' => $word,
                        'boost' => (int)ScoreItems::get('companyName')
                    ]
                ]
            ];

            $query['function_score']['query']['bool']['should'][] = [
                'match_phrase' => [
                    'companyName' => [
                        'query' => $word,
                        'boost' => 1000,
                        "slop" => 2,
                    ]
                ]
            ];
            $query['function_score']['query']['bool']['should'][] = [
                'match_phrase' => [
                    'companyName.keyword' => [
                        'query' => $word,
                        'boost' => 100000
                    ]
                ]
            ];
        }
    }

    /**
     * 根据关键字类型，设置搜索条件
     * @param array $query
     * @param array $keyword
     */
    protected function setKeyWordQueryByKeyType(& $query = [], & $options)
    {

        //针对分类词模糊搜索
        if (isset($options['catWord']) && !empty($options['catWord'])) {
            $this->setCatWordQuery($query, $options['catWord']);
        }

        //针对公司名称模糊搜索
        if (isset($options['companyWord']) && !empty($options['companyWord'])) {
            $this->setCompanyWordQuery($query, $options['companyWord']);
        }
    }

    /**
     * 设置会员充值金额加分项
     * @param array $query
     */
//    protected function setRechargeScore(&$query = [])
//    {
//        $rechargeScoreQuery = &$query['function_score']['functions'];
//        $rechargeScoreQuery[] = [
//            'script_score' => [
//                'script' => "doc['contractedAmount'].value > 0 ? doc['contractedAmount'].value : 1"
//            ]
//        ];
//    }

    /**
     * 基础分类排名权重计算
     * @param array $query
     * @param $basicCategoryCode
     */
    protected function setBasicCategoryCodeWeight(&$query = [], $basicCategoryCode)
    {
        if (empty($basicCategoryCode)) {
            return;
        }
        $rechargeScoreQuery = &$query['function_score']['functions'];
        $scripts = [];

        $basicCategoryCode = array_map(function ($code) {
            return (int)$code;
        }, $basicCategoryCode);
        foreach ($basicCategoryCode as $code) {
            $key = 'categoryCodeRanks.' . $code;
            //$script = "score = score + (doc.containsKey('$key') ? doc['$key'].value : 0)/doc['basicCategoryCode'].length";
            $script = "score = score + (doc.containsKey('$key') ? doc['$key'].value : 0)";
            array_push($scripts, $script);
        }
        $scriptStr = implode(';', $scripts);
        $rechargeScoreQuery[] = [
            'script_score' => [
                'script' => "def score=0;$scriptStr;return score > 0 ? score/2 :1;"
            ]
        ];
    }


    /**
     * 设置会员加分项（不重复加分）
     * @param array $query
     * @param $keyword
     */
    protected function setMemberScore(&$query = [], array $basicCategoryCode, $keyword = [])
    {
        $memberScoreQuery = &$query['function_score']['functions'];
        // 1:钻石 2:铂金 3:金牌 4:认证用户
        $scoreItems = [
            'isDiamond' => 1, 'isPlatinum' => 2, 'isGoldMedal' => 3, 'isRegionalDiamond' => 5
//            'authenticatedUser' => 4 //po 要求去掉
        ];
        if (!empty($basicCategoryCode)) {
            $basicCategoryCode = array_map(function ($code) {
                return (int)$code;
            }, $basicCategoryCode);
        }
        if (!empty($scoreItems)) {
            foreach ($scoreItems as $item => $grade) {
                $weight = (int)ScoreItems::get($item);
                // 当没有搜索词时，付费供应商的weight * 5倍
                // 目的是在自然排序下，把所用的付费供应商提高曝光度
                if (!$keyword) {
                    $weight *= 5;
                }
                if (!empty($basicCategoryCode)) {
                    $memberScoreQuery[] = [
                        'filter' => [
                            'bool' => [
                                'must' => [
                                    [
                                        'term' => [
                                            'supplierLevel' => $grade
                                        ],
                                    ], [
                                        'terms' => [
                                            'mainBusiness' => $basicCategoryCode
                                        ]
                                    ]
                                ]
                            ]
                        ],
                        'weight' => $weight
                    ];
                } else {
                    $memberScoreQuery[] = [
                        'filter' => [
                            'term' => [
                                'supplierLevel' => $grade
                            ]
                        ],
                        'weight' => $weight
                    ];
                }
            }
        }
    }

    /**
     * 设置标签加分项（可累计加分）
     * @param array $query
     */
    public function setTagsScore(&$query = [])
    {
        $tagsScoreQuery = &$query['function_score']['functions'];
        $fields = [
            'isTop10For2020' => 1, // 行业竞争力十强
            'isTop100StrategicCooperation' => true, // 百强战略合作
            'isHighQualityFor2020' => 1 // 高品质供应商
        ];
        if (!empty($fields)) {
            foreach ($fields as $field => $value) {
                $tagsScoreQuery[] = [
                    'filter' => [
                        'term' => [
                            $field => $value
                        ]
                    ]
                    ,
                    'weight' => (int)ScoreItems::get($field)
                ];
            }
        }
    }

    /**
     * 设置基础资料加分项
     * @param array $query
     */
//    public function setBasicDataScore(&$query = [])
//    {
//        $basicDataScoreQuery = &$query['function_score']['functions'];
//        // 1:认证用户1-5 2:认证用户6-10 3::认证用户10-1000
//        $userLevels = [1, 2, 3];
//        if (!empty($userLevels)) {
//            foreach ($userLevels as $g) {
//                $basicDataScoreQuery[] = [
//                    'filter' => [
//                        'term' => [
//                            'userLevel' => $g
//                        ]
//                    ]
//                    ,
//                    'weight' => (int)ScoreItems::get('userLevel' . $g)
//                ];
//            }
//        }
//
//        // 1:注册资本1000—3000 2:注册资本3000—5000 3:注册资本5000以上
//        $registeredCapitaLevels = [1, 2, 3];
//        if (!empty($registeredCapitaLevels)) {
//            foreach ($registeredCapitaLevels as $g) {
//                $basicDataScoreQuery[] = [
//                    'filter' => [
//                        'term' => [
//                            'registeredCapitaLevel' => $g
//                        ]
//                    ]
//                    ,
//                    'weight' => (int)ScoreItems::get('registeredCapital' . $g)
//                ];
//            }
//        }
//    }

    /**
     * 设置开发商推荐加分项
     * @param array $query
     */
//    public function setDeveloperRecommendScore(&$query = [])
//    {
//        $recommendScoreQuery = &$query['function_score']['functions'];
//        // 1:1-10 2:11-20 3:21-50 4:50以上
//        $recommendLevels = [1, 2, 3, 4];
//        if (!empty($recommendLevels)) {
//            foreach ($recommendLevels as $g) {
//                $recommendScoreQuery[] = [
//                    'filter' => [
//                        'term' => [
//                            'recommendLevel' => $g
//                        ]
//                    ]
//                    ,
//                    'weight' => (int)ScoreItems::get('developerRecommend' . $g)
//                ];
//            }
//        }
//    }

    /**
     * 设置附加加分项
     * @param array $query
     */
    public function setAttachedScore(&$query = [])
    {
        $storageScoreQuery = &$query['function_score']['functions'];

        // 项目案例数
        $storageScoreQuery[] = [
            'script_score' => [
                'script' => "def score=0; score = score + doc['projectCount'].value; return score * 2;",
            ]
        ];

        // 被入库数
        $storageScoreQuery[] = [
            'script_score' => [
                'script' => "def score=0; score = score + doc['inStorageCount'].value; return score * 2;",
            ]
        ];

        // 被推荐数
        $storageScoreQuery[] = [
            'script_score' => [
                'script' => "def score=0; score = score + doc['recommendCount'].value; return score * 2;",
            ]
        ];

        // 联系人数
        $storageScoreQuery[] = [
            'script_score' => [
                'script' => "def score=0; score = score + doc['linkNumber'].value; return score <= 0 ? 0 : 1000;",
            ]
        ];
    }

    /**
     * 构建标签项查询
     * @param array $bool
     * @param $boolKey
     * @param array $suppliserTags
     */
    protected function builderSupplierTags
    (
        &$query = [],
        $suppliserTags
    )
    {
        if (!empty($suppliserTags)) {
            $tags = explode(',', $suppliserTags);
            $tags = array_map(function ($code) {
                return (int)$code;
            }, $tags);
            // 当前supplierTags最多只有两个值，暂不需要考虑或关系
            foreach ($tags as $v){
                $query['function_score']['query']['bool']['must'][] = [
                    'term' => [
                        'supplierTags' => $v
                    ]
                ];
            }
        }
    }

    /**
     * 构建精选供应商查询
     * @param array $query
     * @param bool $isBoutique
     */
    protected function builderSupplierBoutique
    (
        &$query = [],
        $isBoutique = ''
    )
    {
        if ($isBoutique == true) {
            $query['function_score']['query']['bool']['must'][] = [
                'term' => [
                    'isBoutique' => $isBoutique
                ]
            ];
        }
    }

    /**
     * 构建是否是砖石供应商
     * @param array $query
     * @param string $isDiamond
     */
    protected function builderSupplierDiamond(&$query = [], $isDiamond = '')
    {
        if ($isDiamond) {
            $query['function_score']['query']['bool']['must'][]["bool"]["should"] =
                [
                    [
                        "bool" =>
                            [
                                "must" =>
                                    [
                                        [
                                            'term' =>
                                                [
                                                    'isDiamondSupplier' => 1
                                                ]
                                        ],
                                        [
                                            'term' =>
                                                [
                                                    'isGoldenSupplier' => 1
                                                ]
                                        ]
                                    ]
                            ]
                    ],
                    [
                        "term" =>
                            [
                                "isRegionalDiamond" => 1
                            ]
                    ]
                ];
        }
    }

    /**
     * 构建服务二级分类查询
     * todo 需要加入行业top分类过滤，避免有的供应商分类太多， 影响搜索结果
     * @param array $query
     * @param $basicCategoryCode
     */
    protected function builderBasicCategoryCodes2
    (
        &$query = [],
        $basicCategoryCodes2
    )
    {
        if (!empty($basicCategoryCodes2)) {
            if (!is_array($basicCategoryCodes2)) {
                $basicCategoryCodes2 = explode(',', $basicCategoryCodes2);
            }
            $basicCategoryCodes2 = array_keys(array_flip($basicCategoryCodes2));

            $basicCategoryCodes2 = array_map(function ($code) {
                return (int)$code;
            }, $basicCategoryCodes2);

            $query['function_score']['query']['bool']['must'][] = [
                'terms' => [
                    $this->matchBasicCategoryCode2 => $basicCategoryCodes2
                ]
            ];
        }
    }

    /**
     * 构建服务分类查询
     * todo 需要加入行业top分类过滤，避免有的供应商分类太多， 影响搜索结果
     * @param array $query
     * @param $basicCategoryCode
     */
    protected function builderBasicCategoryCodes
    (
        &$query = [],
        array $basicCategoryCodes
    )
    {
        if (!empty($basicCategoryCodes)) {
            $basicCategoryCodes = array_map(function ($code) {
                return (int)$code;
            }, $basicCategoryCodes);

            $query['function_score']['query']['bool']['must'][] = [
                'terms' => [
                    $this->matchBasicCategoryCode => $basicCategoryCodes
                ]
            ];
        }
    }

    /**
     * 构建服务区域查询
     * @param array $query
     * @param $serviceLocationCode
     */
    protected function builderServiceLocationCodes
    (
        &$query = [],
        $serviceLocationCodes
    )
    {
        if (!empty($serviceLocationCodes)) {
            if (!is_array($serviceLocationCodes)) {
                $serviceLocationCodes = explode(',', $serviceLocationCodes);
            }

            $region = (new DictionaryService())->getRegionHierarchyByCode($serviceLocationCodes);
            if (!empty($region) && !empty($region->childRegionNodes)) {
                foreach ($region->childRegionNodes as $childRegion) {
                    $serviceLocationCodes[] = $childRegion->code;
                }
            }

            $serviceLocationCodes = array_keys(array_flip($serviceLocationCodes));
            $serviceLocationCodes = array_map(function ($code) {
                return $code == 'china' ? 'china' : (int)$code;
            }, $serviceLocationCodes);

            $query['function_score']['query']['bool']['must'][] = [
                'terms' => [
                    'serviceLocationCode' => $serviceLocationCodes
                ]
            ];
        }
    }

    /**
     * 构建项目所在地查询
     * @param array $query
     * @param $projectLocationCode
     */
    protected function builderProjectLocationCodes
    (
        &$query = [],
        $projectLocationCode
    )
    {
        if (!empty($projectLocationCode)) {
            if (!is_array($projectLocationCode)) {
                $projectLocationCode = explode(',', $projectLocationCode);
            }

            $query['function_score']['query']['bool']['must'][] = [
                'terms' => [
                    'projectLocationCode' => $projectLocationCode
                ]
            ];
        }
    }

    /**
     * 构建注册资金范围查询
     * @param array $bool
     * @param $boolKey
     * @param $registerCapital
     * @param $registerCapitalEnd
     */
    protected function builderRegCapital
    (
        &$query = [],
        $registerCapital,
        $registerCapitalEnd
    )
    {

        $registerCapital = (int)$registerCapital;
        $registerCapitalEnd = (int)$registerCapitalEnd;
        if ($registerCapital == 0 && $registerCapitalEnd == 0) {
            return;
        }

        $range = [];
        $registerCapital = $registerCapital > 0 ? $registerCapital : 0;
        $registerCapitalEnd = $registerCapitalEnd > 0 ? $registerCapitalEnd : 0;
        if ($registerCapital > 0 && $registerCapitalEnd > 0) {
            if ($registerCapital > $registerCapitalEnd) {
                $temp = $registerCapital;
                $registerCapital = $registerCapitalEnd;
                $registerCapitalEnd = $temp;
            }
        }

        if (!empty($registerCapital)) {
            $range['from'] = $registerCapital;
        }
        if (!empty($registerCapitalEnd)) {
            $range['to'] = $registerCapitalEnd;
        }

        if (!empty($range)) {
            $query['function_score']['query']['bool']['must'][] = [
                'range' => [
                    'regCapital' => $range
                ]
            ];
        }
    }

    /**
     * 构建入库次数量范围查询
     * @param array $bool
     * @param $inStorageCount
     */
    protected function builderInStorageCount(&$query = [], $inStorageCount)
    {
        if (!is_numeric($inStorageCount) || $inStorageCount <= 0) {
            return;
        }
        $query['function_score']['query']['bool']['must'][] = [
            'range' => [
                'inStorageCount' => [
                    'gte' => (int)$inStorageCount
                ]
            ]
        ];
    }

    /**
     * 构建项目案例数量范围查询
     * @param array $bool
     * @param $projectCount
     */
    protected function builderProjectCount(&$query = [], $projectCount)
    {
        if (!is_numeric($projectCount) || $projectCount <= 0) {
            return;
        }
        $query['function_score']['query']['bool']['must'][] = [
            'range' => [
                'projectCount' => [
                    'gte' => (int)$projectCount
                ]
            ]
        ];
    }

    /**
     * 构建联系人数量范围查询
     * @param array $query
     * @param $linkNumber
     * @param $channel
     */
    protected function builderLinkNumber(&$query = [], $linkNumber, $channel)
    {
        if ($channel == 'search'){
            if (!is_numeric($linkNumber) || $linkNumber <= 0) {
                $number = 0;
            } else{
                $number = (int)$linkNumber;
            }
            $query['function_score']['query']['bool']['must'][] = [
                'range' => [
                    'linkNumber' => [
                        'gt' => $number
                    ]
                ]
            ];
        } else {
            if (!is_numeric($linkNumber) || $linkNumber <= 0) {
                return;
            }
            $query['function_score']['query']['bool']['must'][] = [
                'range' => [
                    'linkNumber' => [
                        'gte' => (int)$linkNumber
                    ]
                ]
            ];
        }
    }

    /**
     * 构建项目地区查询
     * @param array $bool
     * @param $region
     */
    protected function builerAreaQuery
    (
        &$query = [],
        array $locationCodes,
        $locationType
    )
    {
        if (!empty($locationCodes)) {
            $locations = $locationCodes;
            foreach ($locations as $loc) {
                $location = [$loc];
                $region = (new DictionaryService())->getRegionHierarchyByCode($location);
                if (!empty($region) && !empty($region->childRegionNodes)) {
                    foreach ($region->childRegionNodes as $childRegion) {
                        $locations[] = $childRegion->code;
                    }
                }
            }
            $locations = array_keys(array_flip($locations));
            $locations = array_map(function ($code) {
                return (int)$code;
            }, $locations);
            if ($locationType == 1) {
                $field = 'projectLocationCode'; // （供应商）项目所在地
            } else {
                $field = 'cityCode'; // （供应商）公司所在地
            }
            $condition['bool']['should'] = [
                [
                    'terms' => [
                        $field => $locations
                    ]
                ]
            ];
            $condition['bool']['minimum_should_match'] = 1;

            $query['function_score']['query']['bool']['must'][] = $condition;
        }
    }


    /**
     * 构建上市状态查询
     * @param array $query
     * @param $listedType
     */
    protected function builderListedType(&$query = [], $listedType){
        $query['function_score']['query']['bool']['must'][] = [
            'term' => [
                'listedType' => $listedType
            ]
        ];
    }


    /**
     * 构建营业额查询
     * @param array $query
     * @param $turnoverNum
     */
    protected function builderTurnoverNum(&$query = [], $turnoverNum){
        if (!is_numeric($turnoverNum) || $turnoverNum <= 0) {
            return;
        }
        $query['function_score']['query']['bool']['must'][] = [
            'range' => [
                'turnoverNum' => [
                    'gte' => (int)$turnoverNum
                ]
            ]
        ];
    }


    /**
     * 构建战采数量查询
     * @param array $query
     * @param $strategicCaseNum
     */
    protected function builderStrategicCaseNum(&$query = [], $strategicCaseNum){
        if (!is_numeric($strategicCaseNum) || $strategicCaseNum <= 0) {
            return;
        }
        $query['function_score']['query']['bool']['must'][] = [
            'range' => [
                'strategicCaseNum' => [
                    'gte' => (int)$strategicCaseNum
                ]
            ]
        ];
    }

    //获取供应商搜索，公司名称提示列表
    public function supplierSuggestions($keyword, $size)
    {

        $include = ['companyName', 'supplierId'];

        //高亮处理
        $highlight = [
            'pre_tags' => ['<em class="_high">'],
            'post_tags' => ['</em>'],
            "fields" => [
                "companyName" => new \stdClass(),
            ]
        ];
//        $query = [
//            'match' => [
//                'companyName' => [
//                    'query' => $keyword,
//                    'boost' => (int)(ScoreItems::get('companyName')),
//                ],
//            ],
//        ];
        $query = [
            'bool' => [
                'should' => [
                    [
                        'match' => [
                            'companyName' => [
                                'query' => $keyword,
                                'boost' => (int)(ScoreItems::get('companyName') / 5),
                            ]
                        ]
                    ],
                    [
                        'match' => [
                            'companyName' => [
                                'query' => $keyword,
                                'boost' => (int)(ScoreItems::get('companyName')),
                                "analyzer" => 'ik_smart',
                            ]
                        ]
                    ]
                ]
            ]
        ];
        list($total, $data) = (new IntegrateSupplierRepository())->queryList($query, $include, 0, $size, $highlight, []);
        $return = [];
        if ($total > 0) {
            foreach ($data as $val) {
                $return[] = [
                    'supplier_id' => $val['_source']['supplierId'] ?? '',
                    'company_name' => $val['_source']['companyName'] ?? '',
                    'company_name_hl' => $val['highlight']['companyName'][0] ?? '',
                ];

            }
        }
        return $return;
    }


    public function supplierIsExists($companyNames)
    {
        $condition = [
            'bool' => [
                'must' => [
                    [
                        'terms' => [
                            'companyName.keyword' => $companyNames
                        ]
                    ]
                ]
            ]
        ];
        $existsMap = [];
        $list = (new IntegrateSupplierRepository())->isExists($condition, ['companyName', 'supplierId'], count($companyNames));
        foreach ($list as $item) {
            $existsMap[$item['_source']['companyName']] = $item['_source']['supplierId'];
        }
        return $existsMap;
    }


}
